package com.wenlin.myproduction.widget;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.wenlin.myproduction.R;


/**
 * @author cwl
 * @desc 表示亲密度的爱心，画了一个爱心的path，分别与三张位图取交集，
 * 先画部分粉红色爱心图片做副波浪，再画空的爱心图片作为背景，再画主波浪。
 * @Email 377979485@qq.com
 * @time 2023/11/8/008 16:37
 */
public class HeartView extends View {
    private static final int WAVE_NUM = 4;
    private int viewWidth = (int) dpToPx(85);
    private int viewHeight = (int) dpToPx(75.5f);
    private int waveHeight = viewHeight / 5;
    private int waveLength = viewWidth / WAVE_NUM;
    private int marginBottom = (int) (viewHeight / 227f * 47);
    private int heartHeight = (int) (viewHeight / 227f * 170);
    private Bitmap bitmapBg, bitmapFt, bitmapFt2;
    private Paint paint, paintPath;
    private Path path, pathHeart;
    private PorterDuffXfermode porterDuffXfermode;
    private ValueAnimator valueAnimator;//值动画
    private ValueAnimator progressAnimator;//值动画
    private ValueAnimator scaleAnimator;//值动画
    private float waveFactor;
    private float scaleFactor;
    private int progress;
    private int startY;

    public HeartView(Context context) {
        this(context, null);
    }

    public HeartView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        //画笔
        paint = new Paint();
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setAntiAlias(true);
        paint.setDither(true);
        //路径画笔
        paintPath = new Paint();
        paintPath.setStyle(Paint.Style.FILL_AND_STROKE);
        paintPath.setAntiAlias(true);
        paintPath.setDither(true);
//        paintPath.setColor(Color.GREEN);//cwl 2023/11/10/010 9:42:测试的时候用
        paintPath.setColor(Color.parseColor("#10000000"));
        //裁剪模式
        porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);//模式：显示前景图并取交集（IN）。（SRC source表示源图片，背景图是DST destination目的地）
        //位图
        bitmapBg = BitmapFactory.decodeResource(getResources(), R.mipmap.common_icon_heart_empty);
        bitmapFt = BitmapFactory.decodeResource(getResources(), R.mipmap.common_icon_heart_full);
        bitmapFt2 = BitmapFactory.decodeResource(getResources(), R.mipmap.common_icon_heart_full_2);
        bitmapBg = getBitmapWithTargetWidthHeight(bitmapBg, viewWidth, viewHeight);
        bitmapFt = getBitmapWithTargetWidthHeight(bitmapFt, viewWidth, viewHeight);
        bitmapFt2 = getBitmapWithTargetWidthHeight(bitmapFt2, viewWidth, viewHeight);
        //其他
        path = new Path();
        pathHeart = new Path();
        setProgress(0);
        startWaveAnim();
    }

    /**
     * 设置进度
     *
     * @param progress 进度
     */
    public void setProgress(int progress) {
        if (progress > 100) progress = 100;
        if (progress < 0) progress = 0;
        startProgressAnim(progress);
        this.progress = progress;
    }

    /**
     * 开始缩放的呼吸动画
     */
    private void startScaleAnim() {
        if (scaleAnimator != null && scaleAnimator.isRunning()) {
            scaleAnimator.cancel();
            scaleAnimator = null;
        }
        scaleAnimator = ValueAnimator.ofFloat(1, 1.1f);//cwl 2023/11/10/010 13:31:放大1.1倍，正好不会超出控件本身的范围，主要是上边距
        scaleAnimator.addUpdateListener(animation -> {
            scaleFactor = (float) animation.getAnimatedValue();
            invalidate();
        });
        scaleAnimator.setDuration(500);
        scaleAnimator.setRepeatCount(ValueAnimator.INFINITE);
        scaleAnimator.setRepeatMode(ValueAnimator.REVERSE);
        scaleAnimator.setInterpolator(new LinearInterpolator());
        scaleAnimator.start();
    }

    /**
     * 开始进度变化动画
     */
    private void startProgressAnim(int target) {
        if (progressAnimator != null && progressAnimator.isRunning()) {
            progressAnimator.cancel();
            progressAnimator = null;
        }
        progressAnimator = ValueAnimator.ofInt(progress, target);
        progressAnimator.addUpdateListener(animation -> {
            progress = (int) animation.getAnimatedValue();
            startY = (int) (viewHeight - marginBottom + waveHeight / 2f - ((heartHeight + waveHeight / 2) * progress) / 100f);
            invalidate();
        });
        progressAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(@NonNull Animator animation) {

            }

            @Override
            public void onAnimationEnd(@NonNull Animator animation) {
                if (progress == 100) startScaleAnim();
                else {
                    if (scaleAnimator != null && scaleAnimator.isRunning()) {
                        scaleAnimator.cancel();
                        scaleAnimator = null;
                    }
                }
            }

            @Override
            public void onAnimationCancel(@NonNull Animator animation) {

            }

            @Override
            public void onAnimationRepeat(@NonNull Animator animation) {

            }
        });
        progressAnimator.setDuration(1000);
        progressAnimator.setInterpolator(new LinearInterpolator());
        progressAnimator.start();
    }

    /**
     * 开始波浪动画
     */
    private void startWaveAnim() {
        if (valueAnimator != null && valueAnimator.isRunning()) {
            valueAnimator.cancel();
            valueAnimator = null;
        }
        valueAnimator = ValueAnimator.ofFloat(0, -WAVE_NUM * waveLength * 2);
        valueAnimator.addUpdateListener(animation -> {
            waveFactor = (float) animation.getAnimatedValue();
            invalidate();
        });
        valueAnimator.setDuration(5000);
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setRepeatMode(ValueAnimator.RESTART);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //进度条满时显示缩放动画，这里使用画布缩放实现
        if (scaleAnimator != null && scaleAnimator.isRunning()) {
            canvas.scale(scaleFactor, scaleFactor, viewWidth * 121 / 255f, viewHeight * 94 / 227f);
        }
        //画心的路径
        pathHeart.reset();
        pathHeart.moveTo(viewWidth * 126 / 255f, viewHeight * 23 / 227f);//爱心上面的中心点
        //右半边
        pathHeart.cubicTo(viewWidth * 3.1f / 4f, -viewHeight / 7.4f,
                viewWidth * 17.9f / 16f, viewHeight * 2.15f / 5f,
                viewWidth * 133 / 255f, viewHeight * 176 / 227f);
        //下面平缓过渡
        pathHeart.quadTo(viewWidth * 124 / 255f, viewHeight * 182 / 227f,
                viewWidth * 111 / 255f, viewHeight * 175 / 227f);
        //左半边
        pathHeart.cubicTo(-viewWidth * 1.4f / 16f, viewHeight * 2.49f / 5f,
                viewWidth * 0.34f / 4f, -viewHeight / 7.2f,
                viewWidth * 112 / 255f, viewHeight * 21 / 227f);
        //上面收进去的部分
        pathHeart.quadTo(viewWidth * 122 / 255f, viewHeight * 26 / 227f,
                viewWidth * 126 / 255f, viewHeight * 23 / 227f);
        pathHeart.close();
//        canvas.drawPath(pathHeart, paintPath);
        //画副波浪即浅色波浪
        path.reset();
        path.moveTo(viewWidth - waveFactor + waveLength, startY - waveHeight / 2f);
        for (int i = 0; i < WAVE_NUM * 2; i++) {
            path.rQuadTo(-waveLength / 2f, -waveHeight / 3f, -waveLength, 0);
            path.rQuadTo(-waveLength / 2f, waveHeight / 3f, -waveLength, 0);
        }
        path.lineTo(0, viewHeight);
        path.lineTo(viewWidth, viewHeight);
        path.close();
        path.op(pathHeart, Path.Op.INTERSECT);//两条路径相交取交集
        canvas.drawPath(path, paint);
        canvas.saveLayerAlpha(0, 0, viewWidth, viewHeight, 255);
        canvas.drawPath(path, paint);
        paint.setXfermode(porterDuffXfermode);
        canvas.drawBitmap(bitmapFt2, 0, 0, paint);
        paint.setXfermode(null);
        canvas.restore();
        //画半透明背景图片
        canvas.drawBitmap(bitmapBg, 0, 0, paint);
        //画主波浪即深色波浪
        path.reset();
        path.moveTo(waveFactor, startY - waveHeight / 2f);
        for (int i = 0; i < WAVE_NUM * 2; i++) {
            path.rQuadTo(waveLength / 2f, -waveHeight / 2f, waveLength, 0);
            path.rQuadTo(waveLength / 2f, waveHeight / 2f, waveLength, 0);
        }
        path.lineTo(viewWidth, viewHeight);
        path.lineTo(0, viewHeight);
        path.close();
        path.op(pathHeart, Path.Op.INTERSECT);//两条路径相交取交集
        canvas.drawPath(path, paint);
        canvas.saveLayerAlpha(0, 0, viewWidth, viewHeight, 255);
        canvas.drawPath(path, paint);
        paint.setXfermode(porterDuffXfermode);
        canvas.drawBitmap(bitmapFt, 0, 0, paint);
        paint.setXfermode(null);
        canvas.restore();
    }

    /**
     * 生成新的Bitmap图片
     *
     * @return 所求
     */
    private Bitmap getBitmapWithTargetWidthHeight(Bitmap bitmap, float newWidth, float newHeight) {
        Matrix matrix = new Matrix();
        int width = bitmap.getWidth();//获取图片本身的宽
        int height = bitmap.getHeight();//获取图片本身的高
        float scaleRatioOfWidth = newWidth / (width > 0 ? width : newWidth);//宽度缩放比
        float scaleRatioOfHeight = newHeight / (height > 0 ? height : newHeight);//高度缩放比
        matrix.postScale(scaleRatioOfWidth, scaleRatioOfHeight);
        return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (bitmapBg != null && !bitmapBg.isRecycled()) {
            bitmapBg.recycle();
            bitmapBg = null;
        }
        if (bitmapFt != null && !bitmapFt.isRecycled()) {
            bitmapFt.recycle();
            bitmapFt = null;
        }
        if (bitmapFt2 != null && !bitmapFt2.isRecycled()) {
            bitmapFt2.recycle();
            bitmapFt2 = null;
        }
    }

    /**
     * 获取宽或者高
     *
     * @param measureSpec 测量单位
     * @param isWidSpec   是宽还是高
     * @return 所求
     */
    private int measure(int measureSpec, boolean isWidSpec) {
        int result;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            result = isWidSpec ? viewWidth : viewHeight;
            if (mode == MeasureSpec.AT_MOST) result = Math.min(result, size);
        }
        return result;
    }

    /**
     * 转化长度单位
     *
     * @param dp dp长度
     * @return 对应的px长度
     */
    private float dpToPx(float dp) {
        float scale = getResources().getDisplayMetrics().density;
        return dp * scale;
    }
}
